#include "pcap-ipv6.h"
#include "appender.h"
#include <QDebug>

CPCapIpv6Packet::CPCapIpv6Packet(QObject *parent) :
    CPCapPacket(parent)
{

}

CPCapIpv6Packet::~CPCapIpv6Packet()
{

}

QString CPCapIpv6Packet::nextHeader() const
{
    return m_nextHeader;
}

void CPCapIpv6Packet::setNextHeader(const QString &nextHeader)
{
    m_nextHeader = nextHeader;
    emit nextHeaderChanged();
}

QString CPCapIpv6Packet::hopLimit() const
{
    return m_hopLimit;
}

void CPCapIpv6Packet::setHopLimit(const QString &hopLimit)
{
    m_hopLimit = hopLimit;
    emit hopLimitChanged();
}

QString CPCapIpv6Packet::sourceIp() const
{
    return m_sourceIp;
}

void CPCapIpv6Packet::setSourceIp(const QString &sourceIp)
{
    m_sourceIp = sourceIp;
    emit sourceIpChanged();
}

QString CPCapIpv6Packet::destIp() const
{
    return m_destIp;
}

void CPCapIpv6Packet::setDestIp(const QString &destIp)
{
    m_destIp = destIp;
    emit destIpChanged();
}

int CPCapIpv6Packet::headerLength()
{
    return 40;
}

bool CPCapIpv6Packet::buildHeader(QByteArray &header)
{
    qDebug() << "IPv6: build header";

    if (m_nextHeader.isEmpty()) {
        m_nextHeader = "59";
    }
    if (m_hopLimit.isEmpty()) {
        m_hopLimit = "64";
    }
    if (m_destIp.isEmpty()) {
        m_destIp = "0000:0000:0000:0000:0000:0000:0000:0001";
    }
    if (m_sourceIp.isEmpty()) {
        m_sourceIp = "0000:0000:0000:0000:0000:0000:0000:0002";
    }

    CAppender apd(&header);
    //version (4 bits) + traffic class (8 bits) + flow label (20 bits)
    if (!apd.appendBin("01100000000000000000000000000000")) {
        qCritical() << "IPv6: append version failed";
        return false;
    }
    //payload length (16 bits)
    quint16 length = payloadLength();
    if (!apd.appendUInt16(length)) {
        qCritical() << "IPv6: append payload length failed";
        return false;
    }
    //next header (8 bits)
    if (!apd.appendUInt8(m_nextHeader)) {
        qCritical() << "IPv6: append next header failed";
        return false;
    }
    //hop limit (8 bits)
    if (!apd.appendUInt8(m_hopLimit)) {
        qCritical() << "IPv6: append hop limit failed";
        return false;
    }
    //source address (128 bits)
    QString sourceIp = m_sourceIp;
    sourceIp.replace(":", QString());
    if (sourceIp.length() != 32) {
        return false;
    }
    if (!apd.appendHex(sourceIp)) {
        qCritical() << "IPv6: append src addr failed: " << m_sourceIp;
        return false;
    }
    //destination address (128 bits)
    QString destIp = m_destIp;
    destIp.replace(":", QString());
    if (destIp.length() != 32) {
        return false;
    }
    if (!apd.appendHex(destIp)) {
        qCritical() << "IPv6: append dst addr failed: " << m_destIp;
        return false;
    }
    return true;
}
